<script setup name="test" lang="ts">
import type { ImageInstance, UploadRawFile } from 'element-plus'
import { onMounted, onUnmounted, ref } from 'vue'
import { VueCropper } from 'vue-cropper'
import { ImageCropper } from '~/composables/imageCropper'
import eventBus from '~/eventBus' // 导入事件总线
import 'vue-cropper/dist/index.css'

const cropper = new ImageCropper()

const loading = ref(false)

const imgfile = ref<SelectedImage>()
const img = ref('')

interface previewInfo {
  w: number
  h: number
  div: string
  img: string
  url: string
}

const previews = ref<previewInfo>()
const previewUrl = ref('')

const cropperRef = ref<InstanceType<typeof VueCropper> | null>(null) // vue-cropper 实例

const option = {
  size: 1,
  full: true,
  outputType: 'jpeg',
  canMove: true,
  fixedBox: false,
  original: false,
  canMoveBox: true,
  autoCrop: true,
  autoCropWidth: 19200,
  autoCropHeight: 19200,
  centerBox: true,
  high: true,
  max: 99999,
}
const imageRef = ref<ImageInstance>()

const fixed = ref(false)
const fixedNumber = ref([1, 1])
const showPreview = ref(false)

function realTime(data: previewInfo) {
  previews.value = data
}

function imgLoad() {
  loading.value = false
}

function cropMoving() {

}

function onPreview() {
  showPreview.value = !showPreview.value

  if (showPreview.value) {
    finish()
  }
  imageRef.value!.showPreview()
}
function finish() {
  cropperRef.value.getCropBlob((data: Blob) => {
    previewUrl.value = window.URL.createObjectURL(data)
  })
}

async function rotateLeft() {
  cropperRef.value.rotateLeft()
}

function rotateRight() {
  cropperRef.value.rotateRight()
}

function zoomIn() {
  changeScale(1)
}

function changeScale(num: number) {
  num = num || 1
  cropperRef.value.changeScale(num)
}

function zoomOut() {
  changeScale(-1)
}

function refresh() {
  cropperRef.value.refresh()
}

function save() {
  // event.preventDefault()
  const aLink = document.createElement('a')
  aLink.download = imgfile.value!.name
  // 输出

  cropperRef.value.getCropBlob((data: Blob) => {
    // this.downImg = window.URL.createObjectURL(data)
    aLink.href = window.URL.createObjectURL(data)
    aLink.click()
  })
}

function cropImage() {
  const file = imgfile.value
  if (file) {
    cropperRef.value.getCropBlob(async (result: Blob) => {
      const raw: UploadRawFile = new File([result], file.name, {
        type: result.type,
        lastModified: Date.now(),
      }) as UploadRawFile
      raw.uid = file.uid
      const selectedImage = {
        ...file,
        raw,
      }
      const newImage = await cropper.compressImage(selectedImage, {})
      img.value = newImage.url as string
      imgfile.value = { ...newImage }
      eventBus.emit('croped-file', newImage)
    })
  }
}

function setRatio(_ratio: string, width: number, height: number) {
  if (width === 0) {
    fixed.value = false
    cropperRef.value.refresh()
    return
  }
  // cropperRef.value.setFixedNumber(width, height)
  fixedNumber.value = [width, height]
  fixed.value = true
  cropperRef.value.refresh()
}

function formatFileSize(fileSize: number): string {
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  const index = Math.floor(Math.log(fileSize) / Math.log(1024))
  return `${(fileSize / 1024 ** index).toFixed(2)} ${units[index]}`
}
onMounted(() => {
  eventBus.on('crop-file', handleCropFile) // 监听 croped-file 事件
})

onUnmounted(() => {
  eventBus.off('crop-file', handleCropFile) // 组件卸载时移除监听器
})

function handleCropFile(selectedImage: SelectedImage) {
  // 准备裁剪的文件
  loading.value = true
  if (imgfile.value && imgfile.value.size === selectedImage.size)
    loading.value = false
  imgfile.value = selectedImage
  img.value = selectedImage.url as string
  refresh()
}
</script>

<template>
  <div v-loading="loading" class="center h-full w-full overflow-hidden">
    <div class="w-[calc(100%-160px) p-20 flex h-[calc(100%-80px)] justify-between">
      <div class="mx-auto p-4 bg-green-300 h-[calc(100%-160px)] w-[calc(100%-160px)]">
        <div v-if="imgfile" class="text-xs text-gray-300 mx-auto flex w-[calc(100%-328px)] top-[64px] justify-between fixed">
          <span>{{ imgfile.size ? formatFileSize(imgfile.size) : '' }}</span>
          <span>{{ imgfile.name }}</span>
          <span />
        </div>
        <VueCropper
          ref="cropperRef" :img="img" class="p1" :output-size="option.size" :output-type="option.outputType"
          :info="true" :info-true="true" :full="option.full" :fixed="fixed" :fixed-number="fixedNumber"
          :can-move="option.canMove" :can-move-box="option.canMoveBox" :fixed-box="option.fixedBox"
          :original="option.original" :auto-crop="option.autoCrop" :auto-crop-width="option.autoCropWidth"
          :auto-crop-height="option.autoCropHeight" :center-box="option.centerBox" :high="option.high"
          :max-img-size="option.max" mode="contain" @real-time="realTime" @img-load="imgLoad" @crop-moving="cropMoving"
        />
      </div>
    </div>
  </div>
  <div class="el-image-viewer__btn el-image-viewer__actions">
    <div class="el-image-viewer__actions__inner">
      <el-tooltip content="裁剪比例" placement="top">
        <span i-carbon:document-horizontal class="el-icon">
          <el-dropdown placement="top-start">
            <el-icon class="el-icon--right">
              <span i-carbon:chevron-down />
            </el-icon>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="setRatio('1/1', 0, 0)">
                  自由比例
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('1/1', 200, 200)">
                  1:1
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('3/4', 150, 200)">
                  3:4
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('4/3', 200, 150)">
                  4:3
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('9/16', 112.5, 200)">
                  9:16
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('16/9', 200, 112.5)">
                  16:9
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('2/3', 133.33, 200)">
                  2:3
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('3/2', 200, 133.33)">
                  3:2
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('18/9', 200, 100)">
                  18:9
                </el-dropdown-item>
                <el-dropdown-item @click="setRatio('9/18', 100, 200)">
                  9:18
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </span>
      </el-tooltip>

      <el-tooltip content="向左旋转" placement="top">
        <span class="el-icon" i-carbon:rotate-counterclockwise @click="rotateLeft" />
      </el-tooltip>
      <el-tooltip content="向右旋转" placement="top">
        <span class="el-icon" i-carbon:rotate-clockwise @click="rotateRight" />
      </el-tooltip>
      <el-tooltip content="放大" placement="top">
        <span class="el-icon" i-carbon:zoom-in @click="zoomIn" />
      </el-tooltip>
      <el-tooltip content="缩小" placement="top">
        <span class="el-icon" i-carbon:zoom-out @click="zoomOut" />
      </el-tooltip>
      <el-tooltip content="恢复" placement="top">
        <span class="el-icon" i-carbon:reset @click="refresh" />
      </el-tooltip>
      <el-tooltip content="预览" placement="top">
        <span class="el-icon" i-carbon:image-copy @click="onPreview" />
      </el-tooltip>
      <el-tooltip content="裁剪" placement="top">
        <span class="el-icon" i-carbon:cut-out @click="cropImage" />
      </el-tooltip>
      <el-tooltip content="保存" placement="top">
        <span class="el-icon" i-carbon:save @click="save" />
      </el-tooltip>
    </div>
  </div>

  <!-- 遮罩层 -->
  <div
    v-if="previews && showPreview" class="bg-black bg-opacity-80 flex items-center inset-0 justify-center fixed z-50"
    style="z-index:2004" @click="onPreview"
  >
    <!-- 点击事件阻止冒泡 -->
    <div class="center max-w-[95%]" @click.stop>
      <img :src="previewUrl" alt="示例图片" class="center" object-fit="contain">
    </div>
  </div>
</template>

<style lang="css" scoped>
.el-image-viewer__actions {
  background-color: var(--el-text-color-regular);
  border-color: #fff;
  border-radius: 22px;
  bottom: 30px;
  height: 44px;
  left: 50%;
  padding: 0 23px;
  transform: translateX(-50%);
}

.el-image-viewer__btn {
  align-items: center;
  /* border-radius: 50%; */
  box-sizing: border-box;
  cursor: pointer;
  display: flex;
  justify-content: center;
  opacity: 0.8;
  position: absolute;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  z-index: 1;
}

.el-image-viewer__actions__inner {
  align-items: center;
  color: #fff;
  cursor: default;
  display: flex;
  font-size: 23px;
  gap: 22px;
  height: 100%;
  justify-content: space-around;
  padding: 0 6px;
  width: 100%;
}
</style>
